package com.yenlien.traceyun.business.service;

import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.business.bean.Search;
import com.yenlien.traceyun.business.dao.*;
import com.yenlien.traceyun.business.entity.*;
import com.yenlien.traceyun.business.interceptor.UserAuthUtil;
import com.yenlien.traceyun.business.service.rest.usercenter.CompanyRestService;
import com.yenlien.traceyun.business.trace.TraceInfo;
import com.yenlien.traceyun.business.trace.TraceService;
import com.yenlien.traceyun.common.utils.RandomUtil;
import com.yenlien.traceyun.common.utils.Tools;
import com.yenlien.traceyun.webase.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class SubpackageService {
    @Autowired
    private SubpackageDao subpackageDao;
    @Autowired
    private BoxDao boxDao;
    @Autowired
    private CompanyRestService companyRestService;
    @Autowired
    private PrintMsgDao printMsgDao;
    @Autowired
    private JdbcTemplate jdbc;

    @Autowired
    private SpaceBoxRecordDao spaceBoxRecordDao;

    @Autowired
    private TraceService traceService;

    @Autowired
    private StorageManageDetailedDao storageManageDetailedDao;

    @Autowired
    private StorageManageDao storageManageDao;

    @Autowired
    private ProductDao productDao;

    @Value("${traceyun.app.id}")
    private String appId;
//    @Value("${traceyun.basePath}")
    private String basePath;


    public Page<Subpackage> findByList(final Subpackage subpackage) {
        Pageable pageable = PageRequest.of(subpackage.getPage(), subpackage.getPageSize(), Sort.Direction.DESC, ("createtime"));
        try {
            Page<Subpackage> all = subpackageDao.findAll(new Specification<Subpackage>() {
                private static final long serialVersionUID = -1396496630802017658L;
                @Override
                public Predicate toPredicate(Root<Subpackage> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    Path<String> source = root.get("source");
                    Path<String> productName = root.get("productName");
                    //构造查询条件
                    List<Predicate> list = new ArrayList<Predicate>();
                    list.add(cb.equal(root.get("companyId"), subpackage.getCompanyId()));
                    if (!StringUtils .isEmpty(subpackage.getSource())) {
                        list.add(cb.equal(source, subpackage.getSource()));
                    }
                    if (!StringUtils.isEmpty(subpackage.getAppId())) {
                        list.add(cb.equal(root.get("appId"), subpackage.getAppId()));
                    }
                    if (StringUtils.isNotEmpty(subpackage.getProductName())) {
                        list.add(cb.like(productName, "%" + subpackage.getProductName() + "%"));
                    }
                    if (StringUtils.isNotEmpty(subpackage.getTypes()) && subpackage.getTypes().equals("1")) {
                        list.add(cb.equal(root.get("genCoded"), subpackage.isGenCoded()));        //打印后页面就不再显示了
                    }
//
                    if (StringUtils.isNotEmpty(subpackage.getTypes())) {
                        list.add(cb.equal(root.get("types"), subpackage.getTypes()));       //分包类型
                    }
//                    if (subpackage.getPrintNumber() > 0) {
//                        list.add(cb.greaterThan(root.get("printNumber"), 0));
//                    }
                    Predicate[] predicate = new Predicate[list.size()];
                    Predicate pre_and = cb.and(list.toArray(predicate));
                    return pre_and;
                }
            }, pageable);
            List<Subpackage> subpackages = new ArrayList<>();
            List<Subpackage> content = all.getContent();
            for (Subpackage spackage1 : content) {
                String id = spackage1.getId();
                String batch = spackage1.getBatch();
                if (id != null && batch != null) {
                    int activationSum = boxDao.isActivationSum2(batch);//统计未激活的赋码数量
                    spackage1.setActivationSum(activationSum);
                    //获取产品图片
                    List<Product> byRelated = productDao.findByRelated(spackage1.getCompanyId(), spackage1.getUserId(), spackage1.getProductName());
                    if (byRelated.size() > 0 && byRelated.get(0) != null && byRelated.get(0).getImg() != null) {
                        spackage1.setImg(byRelated.get(0).getImg());
                    }
                    subpackages.add(spackage1);
                }
            }
            Page<Subpackage> pageImpianto = new PageImpl<Subpackage>(subpackages, pageable, all.getTotalElements());
            return pageImpianto;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new PageImpl<>(new ArrayList<>(), pageable, 0);
    }


    public List<Subpackage> findByRelevanceId(String relevanceId) {
        return subpackageDao.findByRelevanceId(relevanceId);
    }

    @Transactional
    public String print(JSONObject params) {
        Subpackage subpackage = subpackageDao.findById(params.getString("subpackageId"));
        if (subpackage == null) {
            throw new BusinessException("A0001", "数据有误");
        }
        if (subpackage.getSubNumber() < params.getInteger("num")) {
            throw new BusinessException("A0001", "剩余打码量不足");
        }
        subpackage.setPrintNumber(subpackage.getPrintNumber() + params.getIntValue("num"));
        subpackage.setSubNumber(subpackage.getSubNumber() - params.getInteger("num"));
        subpackageDao.save(subpackage);

        PrintMsg printMsg = new PrintMsg();
        printMsg.setSubpackageId(params.getString("subpackageId"));
        printMsg.setContent(params.getString("content"));
        printMsg.setType(params.getString("type"));
        JSONObject json = new JSONObject();
        printMsgDao.save(printMsg);
        return printMsg.getId();
    }

    public JSONObject findPrintMsg(String subpackageId) {
        Subpackage subpackage = subpackageDao.findById(subpackageId);
        JSONObject json = new JSONObject();
        json.put("productName", subpackage.getProductName());
        json.put("batch", subpackage.getBatch());
        json.put("spec", subpackage.getSpec());
        json.put("specUnits", subpackage.getSpecUnits());

        JSONObject obj = (JSONObject) companyRestService.findById(subpackage.getCompanyId());
        json.put("company", obj.get("name"));

        return json;
    }

    //在线打印
    public JSONObject onLinePrint(String printMsgId, String subpackageId, int num, String companyId) {
        JSONObject json = new JSONObject();
        PrintMsg printMsg = printMsgDao.findById(printMsgId);
        List<Box> boxList = new ArrayList<>();
        List<String> list = new ArrayList<>();
        //=================新增码表数据开始=================
        String sql = "insert into t_plant_box (id,last_step,source_code,subpackage_id,print_msg_id,company_id)" +
                " values (?,?,?,?,?,?)";
        List<Object[]> batchArgs = new ArrayList<Object[]>();
        for (int i = 0; i < num; i++) {
            String code = Tools.random(20);
            list.add(code);
            batchArgs.add(new Object[]{UUID.randomUUID().toString().replaceAll("-", ""), "", code,
                    printMsg.getSubpackageId(), printMsgId, companyId});
        }
        jdbc.batchUpdate(sql, batchArgs);
        //=================新增码表数据结束=================
        json.put("code", "200");
        json.put("printMsg", printMsg);
        json.put("boxList", list);
        return json;
    }

    @Transactional
    public List<String> getCode(JSONObject params) {
        Subpackage subpackage = subpackageDao.findById(params.getString("subpackageId"));
        if (subpackage == null) {
            throw new BusinessException("A0001", "数据有误");
        }
        //防止覆盖空码激活的情况
        int branchPackageNum = subpackage.getBranchPackageNum();        //分包数量
        int activationSum = boxDao.isActivationSum2(subpackage.getBatch());        //激活数量
        if (activationSum == branchPackageNum) {
            throw new BusinessException("500", "当前分包数已经全部关联追溯码");
        }
        if (!subpackage.isGenCoded()) {
            // 插入生产日期
            Date time = null;
//			try {
//				time = new SimpleDateFormat("yyyy/MM/dd").parse(JSONObject.parseObject(params.getString("content")).getString("生产日期"));
//			} catch (ParseException e) {
//				e.printStackTrace();
//			}
            PrintMsg printMsg = new PrintMsg();
            printMsg.setSubpackageId(params.getString("subpackageId"));
            printMsg.setContent(params.getString("content"));
            printMsg.setType(params.getString("type"));
            printMsg.setCreatetime(time);
            printMsg.setCreatetime(new Date());
            printMsgDao.save(printMsg);

            List<String> list = new ArrayList<>();
            //=================新增码表数据开始=================
            Date date = new Date();
            String sql = "insert into t_plant_box (id,source_code,subpackage_id,print_msg_id,company_id,subpackage_batch,createtime)" +
                    " values (?,?,?,?,?,?,?)";
            List<Object[]> batchArgs = new ArrayList<Object[]>();
            for (int i = 0; i < params.getInteger("num"); i++) {
                //生成离线码
                String code = Tools.random(20);
                list.add(code);
                batchArgs.add(new Object[]{UUID.randomUUID().toString().replaceAll("-", ""), code,
                        printMsg.getSubpackageId(), printMsg.getId(), params.getString("companyId"), subpackage.getBatch(), date});
            }
            jdbc.batchUpdate(sql, batchArgs);
            subpackage.setGenCoded(true);
            subpackageDao.save(subpackage);
            //=================新增码表数据结束=================
            return list;
        } else {
            return boxDao.findBySubId(subpackage.getId());
        }

    }

    public void save(Subpackage subpackage) {
        subpackageDao.save(subpackage);
    }

    /**
     * 空码激活
     *
     * @param subId
     * @param codes
     */
    @Transactional
    public void activeSpaceCode(String subId, List<String> codes) {
        if (codes != null && codes.size() > 0) {
            Subpackage subpackage = subpackageDao.findById(subId);
//			if(subpackage.isGenCoded()){
//				throw new BusinessException("500","已下载或者已关联过空码");
//			}
            int branchPackageNum = subpackage.getBranchPackageNum();        //分包数量
            int activationSum = boxDao.isActivationSum2(subpackage.getBatch());        //激活数量
            if (activationSum == branchPackageNum) {
                throw new BusinessException("500", "当前分包数已经全部关联追溯码");
            }
            //追溯码去重http://172.29.141.109:8881/scan/index.html?code=35607396217472861116

            for (String code : codes) {
                if (code.contains("http")) {
                    String[] split = code.split("\\?");
                    String[] split1 = split[1].split("\\=");
                    code = split1[1];
                    if (code.contains("\\,")) {
                        String[] split2 = code.split("\\,");
                        code = split2[0];
                    }
                }
                Box bySourceCode = boxDao.findSourceCode(code);
                if (bySourceCode != null) {
                    throw new BusinessException("500", "追溯码：" + bySourceCode.getSourceCode() + "重复激活，请重新匹配追溯码");
                }
            }
            String companyId = UserAuthUtil.getLoginUser().getCompanyId();
            List<Box> boxes = new ArrayList<>();
            Date date = new Date();
            for (String item : codes) {
                Box box = new Box();
                box.setAppId(appId);
                box.setCompanyId(companyId);
                box.setSourceCode(item);
                box.setSubpackageId(subpackage.getId());
                box.setSubpackageBatch(subpackage.getBatch());
                box.setCreatetime(date);
                boxes.add(box);
            }
            boxDao.saveAll(boxes);
            subpackage.setGenCoded(true);
            subpackageDao.save(subpackage);
        }
    }

    /**
     * 申请空码
     *
     * @param record
     * @return
     */
    public SpaceBoxRecord apply(SpaceBoxRecord record) {
        record.setAppId(appId);
        record.setCompanyId(UserAuthUtil.getLoginUser().getCompanyId());
        JSONObject obj = (JSONObject) companyRestService.findById(record.getCompanyId());
        record.setCompanyName(obj.getString("name"));
        record.setCreatetime(new Date());
        return spaceBoxRecordDao.save(record);
    }

    /**
     * 申请空码H5
     *
     * @param record
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public List<String> codeH5(SpaceBoxRecord record) {
        record.setAppId(appId);
        record.setCompanyId(UserAuthUtil.getLoginUser().getCompanyId());
        JSONObject obj = (JSONObject) companyRestService.findById(record.getCompanyId());
        record.setCompanyName(obj.getString("name"));
        record.setCreatetime(new Date());
        SpaceBoxRecord recordsave = spaceBoxRecordDao.save(record);

        //防止覆盖空码激活的情况
        Subpackage subpackage = subpackageDao.findById(record.getSubId());
        int branchPackageNum = subpackage.getBranchPackageNum();        //分包数量
        int activationSum = boxDao.isActivationSum2(subpackage.getBatch());        //激活数量
        if (activationSum == branchPackageNum) {
            throw new BusinessException("500", "当前分包数已经全部关联追溯码");
        }
        record.setDownloaded(true);
        List<String> codes = new ArrayList<>();
        List<String> codelist = new ArrayList<>();
//        String basePath = "http://app.cpzsyun.com/scan/index.html?code=";
        try {
            JSONObject parentById = (JSONObject) companyRestService.findParentById(UserAuthUtil.getLoginUser().getCompanyId());
            String name = parentById.getJSONObject("data").getString("name");
            if(basePath.contains("/pscan")){
                basePath =  name.contains("岳池") ? "http://yuechi.cpzsyun.com/pscan/index.html?code=" :
                        name.contains("茂县") ? "http://maoxian.cpzsyun.com/pscan/index.html?code=" :
                                name.contains("彭州") ? "http://pengzhou.cpzsyun.com/pscan/index.html?code=" : basePath;
            }else {
                basePath =  name.contains("岳池") ? "http://yuechi.cpzsyun.com/scan/index.html?code=" :
                        name.contains("茂县") ? "http://maoxian.cpzsyun.com/scan/index.html?code=" :
                                name.contains("彭州") ? "http://pengzhou.cpzsyun.com/scan/index.html?code=" : basePath;
            }
        }catch (Exception e){
            System.out.println("请求usercenter company/findParentById/ 失败");
        }
        for (int i = 0; i < recordsave.getBoxNum(); i++) {
            String uuid = RandomUtil.uuid();
            codes.add(uuid);
            codelist.add(basePath + uuid);
        }
        List<Box> boxes = new ArrayList<>();
        Date date = new Date();
        for (String item : codes) {
            Box box = new Box();
            box.setAppId(appId);
            box.setCompanyId(record.getCompanyId());
            box.setSourceCode(item);
            box.setSubpackageId(record.getSubId());
            box.setSubpackageBatch(record.getSubpackageBatch());
            box.setCreatetime(date);
            boxes.add(box);
        }
        boxDao.saveAll(boxes);
        subpackage.setGenCoded(true);
        subpackageDao.save(subpackage);
        return codelist;
    }

    /**
     * 下载空码
     *
     * @param spaceBoxRecordId
     * @param response
     */
    public void downloadSpaceBox(int spaceBoxRecordId, String batch, HttpServletRequest request, HttpServletResponse response) throws IOException {
        SpaceBoxRecord record = spaceBoxRecordDao.findById(spaceBoxRecordId).get();
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=box.txt");
        ByteArrayOutputStream bOutput = new ByteArrayOutputStream(12);
        record.setDownloaded(true);
//        String basePath = "http://app.cpzsyun.com/scan/index.html?code=";
        try {
            JSONObject parentById = (JSONObject) companyRestService.findParentById(UserAuthUtil.getLoginUser().getCompanyId());
            String name = parentById.getJSONObject("data").getString("name");
            if(basePath.contains("/pscan")){
                basePath =  name.contains("岳池") ? "http://yuechi.cpzsyun.com/pscan/index.html?code=" :
                        name.contains("茂县") ? "http://maoxian.cpzsyun.com/pscan/index.html?code=" :
                                name.contains("彭州") ? "http://pengzhou.cpzsyun.com/pscan/index.html?code=" : basePath;
            }else {
                basePath =  name.contains("岳池") ? "http://yuechi.cpzsyun.com/scan/index.html?code=" :
                        name.contains("茂县") ? "http://maoxian.cpzsyun.com/scan/index.html?code=" :
                                name.contains("彭州") ? "http://pengzhou.cpzsyun.com/scan/index.html?code=" : basePath;
            }
        }catch (Exception e){
            System.out.println("请求usercenter company/findParentById/ 失败");
        }
        spaceBoxRecordDao.save(record);
        int boxNum = record.getBoxNum();
        for (int i = 0; i < boxNum; i++) {
            if((boxNum - 1) == i){
                bOutput.write((basePath + RandomUtil.uuid()).getBytes());
            }else {
                bOutput.write((basePath + RandomUtil.uuid() + "\r\n").getBytes());
            }
        }
        response.getOutputStream().write(bOutput.toByteArray());
    }


    /**
     * 上传空码激活空码
     *
     * @param request
     */
    public void uploadActive(HttpServletRequest request) throws IOException {
        MultipartFile file = ((MultipartHttpServletRequest) request).getFile("file");
        String subId = request.getParameter("subId");
        BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()));
        String temp;
        List<String> codes = new ArrayList<>();
        while ((temp = reader.readLine()) != null) {
            codes.add(temp);
        }
        activeSpaceCode(subId, codes);
    }

    /**
     * 分包并生成码
     *
     * @param subpackage
     * @return
     */
    public Subpackage subAndGenreateCode(Subpackage subpackage) {
        subpackage.setGenCoded(true);
        Subpackage p = subpackageDao.save(subpackage);
        List<Box> boxList = new ArrayList<>();
        String sql = "insert into t_plant_box (id,source_code,subpackage_id,print_msg_id,company_id,subpackage_batch,app_id,createtime)" +
                " values (?,?,?,?,?,?,?,?)";
        List<Object[]> batchArgs = new ArrayList<Object[]>();
        Date date = new Date();
        for (int i = 0; i < subpackage.getSubNumber(); i++) {
            String code = Tools.random(20);
            batchArgs.add(new Object[]{UUID.randomUUID().toString().replaceAll("-", ""), code,
                    p.getId(), "", p.getCompanyId(), p.getBatch(), p.getAppId(), date});
        }
        jdbc.batchUpdate(sql, batchArgs);

        if (subpackage.getSource().equals("采购分包")) {
            StorageManage storageManage = storageManageDao.findById(subpackage.getRelevanceId());
            CodeInfo codeInfo = new CodeInfo();
            codeInfo.setAppId(appId);
            codeInfo.setCompanyId(UserAuthUtil.getLoginUser().getCompanyId());
            codeInfo.setCode(p.getBatch());
            codeInfo.setBatchNo(p.getBatch());
            codeInfo.setCreatetime(new Date());
            TraceInfo traceInfo = new TraceInfo();
            traceInfo.setStep("storageManage");
            traceInfo.setInfo(storageManage);
            List<TraceInfo> children = new ArrayList<>();
            TraceInfo child = new TraceInfo();
            child.setStep("storageManageDetailed");
            List<StorageManageDetailed> detaileds = storageManageDetailedDao.findByStorageManageId(storageManage.getId());
            child.setInfo(detaileds);
            children.add(child);
            traceInfo.setChildren(children);
            codeInfo.setContent(JSONObject.toJSONString(traceInfo));
            traceService.addCodeInfo(codeInfo);
        }
        return p;
    }

    /**
     * 获取申请空码记录表
     *
     * @param search
     * @return
     */
    public Page<SpaceBoxRecord> pageSpace(Search search) {
        Pageable pageable = PageRequest.of(search.getPageno() == -1 ? 0 : search.getPageno(), search.getPagesize(), Sort.Direction.DESC, ("createtime"));
        return spaceBoxRecordDao.findByCompanyIdAndAppId(UserAuthUtil.getLoginUser().getCompanyId(), appId, pageable);
    }

    public void upPrint(String id, String print) {
        Subpackage byId = subpackageDao.findById(id);
        Integer integer = Integer.valueOf(print);
        byId.setPrintNumber(integer);
        subpackageDao.save(byId);
    }

    /**
     * 统计该企业总的分包数量
     */
    public Object sumBranchPackage(String compancyId) {
        return subpackageDao.sumBranchPackage(compancyId);
    }

    public Subpackage findById(String id) {
        return subpackageDao.findById(id);
    }
}
